package com.mynetty.netty01;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerAppender;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;

public class TimeServer {

	public static void bind(int port){
		EventLoopGroup masterGroup = new NioEventLoopGroup();
		EventLoopGroup workGroup = new NioEventLoopGroup();
		
		ServerBootstrap bootstrap = new ServerBootstrap();
		bootstrap.group(masterGroup, workGroup)
				.channel(NioServerSocketChannel.class)
				.option(ChannelOption.SO_BACKLOG, 1024)  //连接书，完成三次握手的连接队列
		        .option(ChannelOption.TCP_NODELAY, true)  //不延迟，立即推送
		        .childHandler(new ChildChannelHandler());
		
		System.out.println("绑定端口，同步等待成功。。。。");
		
		try {
			ChannelFuture future = bootstrap.bind(port).sync();
			//等待服务端监控端口关闭
			future.channel().closeFuture().sync();
			System.out.println("等待服务端监控端口关闭。。。。。");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally {
			
			masterGroup.shutdownGracefully();
			workGroup.shutdownGracefully();
			System.out.println("优雅退出释放线程池。。。");
			
		}
		
		
		
	}
	
	private static class ChildChannelHandler extends ChannelInitializer{

		@Override
		protected void initChannel(Channel channel) throws Exception {
			
			channel.pipeline().addLast(new TimeServerHandler()); //往通道中添加i/o事件处理类
		}
		
		
		private static class TimeServerHandler extends ChannelHandlerAdapter{


			@Override
			public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
				// channelRead方法中的msg参数，代表客户端发来的消息，强转成ByteBuf类型
				ByteBuf buf = (ByteBuf) msg;
				byte[] req = new byte[buf.readableBytes()];  //  开辟一个 msg大小的 byte数组
				buf.readBytes(req);  //读取消息到 req数组
				String body = new String(req, "UTF-8");
				System.out.println("客户端说：" + body);
				
				ByteBuf resp = Unpooled.copiedBuffer("服务器端说：hello client!".getBytes());
				ctx.write(resp); // 将消息放入缓存数值
				
			}

			@Override
			public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {

				 ctx.flush();
			}
			
			
			@Override
			public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
				ctx.close(); // 发生异常时候，执行重写后的exceptionCaught 进行资源关闭
			}
			
			
		}
	}
	
	public static void main(String[] args){
		
		TimeServer.bind(4040);
	}
	
	
}
